package com.qf.service.Impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.exception.SmsInterfaceException;
import com.qf.feign.CacheService;
import com.qf.service.PushSubmitToQueueService;
import com.qf.service.SmsCheckService;
import com.qianfeng.smsplatform.common.constants.CacheConstants;
import com.qianfeng.smsplatform.common.constants.InterfaceExceptionDict;
import com.qianfeng.smsplatform.common.model.Standard_Submit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author 徐老板
 * @date 2020/2/27   20:02
 */
@Service
public class SmsCheckServiceImpl implements SmsCheckService {
    private static final  Logger LOGGER = LoggerFactory.getLogger(SmsCheckServiceImpl.class);

    @Resource
    private CacheService cacheService;
    @Resource
    private PushSubmitToQueueService pushSubmitToQueueService;
    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void checkSms(String clientId, String pwd, String srcID, String ip, String content, String mobile) throws JsonProcessingException {

        Integer id;//客户端 id,此处用 int 的原因是你做梦都不敢梦到你有几十亿的客户
        Long sourceId;//下行编号,此处用 long 的 原因是因为短信可能会非常多,会超出 int 的最大值
        try {
            id = Integer.parseInt(clientId);
            LOGGER.error("SmsCheckServiceImpl校验参数传过来解析之后的id是{}",id);
        } catch (Exception e) {
//          e.printStackTrace();
            //代表传递的 id 不合法,需要返回错误信息给用户
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_CLIENTID_ERROR, "客户id错误");
        }

        try {
            sourceId = Long.parseLong(srcID);
        } catch (Exception e) {
            // e.printStackTrace();
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_SRCID_ERROR, "SRCID 错误");
        }

// =======================================从这个地方开始区分=============================================================
        Map clientInfoMap = cacheService.hmget(CacheConstants.CACHE_PREFIX_CLIENT + id);
        LOGGER.error("key是{}",CacheConstants.CACHE_PREFIX_CLIENT + id);
        if (clientInfoMap == null || clientInfoMap.size() == 0) {
            //代表没有这个用户,我们应该抛出异常告诉客户端
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_CLIENTID_ERROR, "没有这个客户id");
        }

        if (StringUtils.isEmpty(ip) || !ip.equalsIgnoreCase((String) clientInfoMap.get("ipaddress"))) {
            //代码传递的 ip 不符合
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_IP_ERROR, "IP地址非法");
        }

        // String md5DigestAsHex = DigestUtils.md5DigestAsHex(pwd.getBytes());//获取传递的密码的 md5 值

        // LOGGER.error("传递的密码的 MD5:{}", md5DigestAsHex);

//        if (StringUtils.isEmpty(pwd)  || ! DigestUtils.md5DigestAsHex(pwd.getBytes()).equalsIgnoreCase((String) clientInfoMap.get("pwd"))) {
//            //代码传递的 ip 不符合
//            LOGGER.error("后台的密码是{}",(String) clientInfoMap.get("pwd"));
//            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_PWD_ERROR, "密码错误");
//        }
        if (StringUtils.isEmpty(content)  || content.length() > 500) {
            //短信的内容不符合
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_MESSAGE_ERROR, "内容长度不符合要求");
        }
        if (StringUtils.isEmpty(mobile)) {
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_MOBILE_ERROR, "手机号为空");
        }

        String[] mobiles = mobile.split(",");//拿到传递的所有的手机号
        if (mobiles.length > 100) {
            //超出了发送号码的最大上限,其实这个上限是可以定义的,每个用户可能都不一样,所以实际开发中是有默认值,可以用单个用户单独定义的,可以保存在 redis 中
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_MOBILE_ERROR, "手机号数量超出限制");
        }

        Map<String, List<String>> checkMobile = checkMobile(mobiles);//校验手机号后得到的 map

        //我们知道可能会有失败的手机号,也有成功的,一定要注意,失败的应该是最后才判断
        List<String> success = checkMobile.get("success");
        List<Standard_Submit> standard_submits = new ArrayList<>();//用于封装短信相关数据的对象集合,用于将正常的手机和内容封装起来
        for (String mobilenumer : success) {
            Standard_Submit standard_submit = new Standard_Submit();
            //保持信息
            standard_submit.setClientID(id);
            standard_submit.setSrcSequenceId(sourceId);
            standard_submit.setDestMobile(mobilenumer);
            standard_submit.setMessageContent(content);
            standard_submit.setSendTime(new Date());

            /**
             * 获取用户类型 1 代表从interface端 2 代表总webmaster端 即后台管理端
             */
            int usertype = (int)clientInfoMap.get("usertype");
            standard_submit.setSource(usertype);
            standard_submits.add(standard_submit);
        }
        //发送数据到下一个流程
        LOGGER.error("发送到下个流程的手机号是:{}", standard_submits);

        pushSubmitToQueueService.sendSmsSubitToQueue(standard_submits);//将这些数据发送到 mq


        //判断有没有需要返回的数据(错误的手机号)
        List<String> fail = checkMobile.get("fail");
        if (fail.size()>0) {
            //有不符合要求的电话号码
            //将这些电话号码返回给用户
            throw new SmsInterfaceException(InterfaceExceptionDict.RETURN_STATUS_MOBILE_ERROR, objectMapper.writeValueAsString(fail));

        }

    }

    /**
     * 校验手机号,合法的保存到 success 这个 key,不合法的保存到 fail 这个 key
     * @param mobiles
     * @return
     */
    private Map<String, List<String>> checkMobile(String[] mobiles) {
        //我们要判断传递过来的手机号是不是一个合法的手机号
        List<String> success = new ArrayList<>();//保存校验成功的手机号的集合
        List<String> fail = new ArrayList<>();//保存校验失败的手机号的集合
        Map<String, List<String>> result = new HashMap<>();
        result.put("success", success);
        result.put("fail", fail);
        //如果不是合法的手机号怎么处理?正常来说 应该是正常的手机号继续发送短信,非法的手机号最终给用户返回一个接口告诉他这些手机号是有问题的
        String regex = "^((13[0-9])|(14[579])|(15([0-3]|[5-9]))|(166)|(17[0135678])|(18[0-9])|(19[8|9]))\\d{8}$";
        for (String mobile : mobiles) {
            boolean matches = mobile.matches(regex);//判断手机号是否合法
            if (matches) {
                success.add(mobile);
            }else{
                fail.add(mobile);
            }
        }


        return result;

    }
}
